package com.example.concurrentprogramming8016.thread.cas;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicStampedReference;
import java.util.concurrent.locks.LockSupport;

/**
 * @author liyanhao
 * @Date 2023-01-04 1:58
 * 使用原子引用解决ABA问题
 */
@Slf4j
public class AtomicStampedReferenceTest {

    public static void main(String[] args) {
        //定义AtomicStampedReference 初始引用1 初始标记为 0
        AtomicStampedReference<Integer> atomicStampedReference
                = new AtomicStampedReference<>(1, 0);
        new Thread(() -> {
            Integer value = atomicStampedReference.getReference();
            int stamp = atomicStampedReference.getStamp();
            System.out.println("获得value为：" + value + "stamp:" + stamp);
            //阻塞一秒
            LockSupport.parkNanos(1000 * 1000 * 1000L);
            if (atomicStampedReference.compareAndSet(value, 2, stamp, stamp + 1)) {
                log.debug("thrad1 update from " + value + " to 2");
            }else {
                log.debug("thread1 update fail!");
            }
        },"thead1").start();

        new Thread(() -> {
            Integer value = atomicStampedReference.getReference();
            int stamp = atomicStampedReference.getStamp();
            System.out.println("获得value为：" + value + "stamp:" + stamp);
            if (atomicStampedReference.compareAndSet(value, 2, stamp, stamp + 1)) {
                log.debug("thrad2 update from " + value + " to 2");
                int stamp2 = atomicStampedReference.getStamp();
                if (atomicStampedReference.compareAndSet(2, 1, stamp2, stamp2 + 1)) {
                    log.debug("thrad2 update from " + value + " to 1");
                }
            }
        }, "thread2").start();

    }
}
